pub use crate::mem::phys_to_virt;

pub use super::regs::*;
pub use super::types::*;

impl GpioController {
    pub fn new(base: usize) -> &'static mut Self {
        let b = base as *mut GpioController;
        unsafe { &mut (*b) }
    }

    pub fn set_pin_dir(&mut self, pin: GpioPins, dir: bool) {
        let mut status = self.dir.0.bits();
        debug!("dir data = {status}");
        let pb = pin.bits();
        if dir == true {
            status |= pb;
        } else {
            status &= !pb;
        }
        debug!("dir data = {status}");
        self.dir.0 = GpioPins::from_bits_truncate(status);
    }

    pub fn set_pin_data(&mut self, pin: GpioPins, data: bool) {
        let mut status = self.dir.0.bits();
        debug!(" data = {status}");
        let pb = pin.bits();
        if data == true {
            status |= pb;
        } else {
            status &= !pb;
        }
        debug!(" data = {status}");
        self.data.0 = GpioPins::from_bits_truncate(status);
    }
}

impl GpioSystem {
    pub fn new() -> Self {
        let base = phys_to_virt(BASE1).into();
        Self {
            controllers: [GpioController::new(base)],
        }
    }

    pub fn controller(&mut self, index: usize) -> Option<&mut GpioController> {
        info!("Getting gpio controller {}", index);
        if index < GPIO_CONTROLLERS {
            Some(&mut self.controllers[index])
        } else {
            None
        }
    }
}
